package com.endlessblue.visa.controller;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.endlessblue.visa.model.User;
import com.endlessblue.visa.model.UserExample;
import com.endlessblue.visa.service.SequenceService;
import com.endlessblue.visa.service.UserService;
import com.endlessblue.visa.util.ALISMSUtil;
import com.endlessblue.visa.util.BeanUtil;
import com.endlessblue.visa.util.CacheUtil;
import com.endlessblue.visa.util.MD5Util;
import com.endlessblue.visa.util.RequestUtil;
import com.endlessblue.visa.util.SessionCacheUtil;
import com.endlessblue.visa.util.StringUtil;
import com.endlessblue.visa.vo.BusiCode;
import com.endlessblue.visa.vo.BusiResult;
import com.endlessblue.visa.vo.CacheType;
import com.endlessblue.visa.vo.ReqParamCheck;
import com.endlessblue.visa.vo.ReqParamCheck.InterfaceType;


@RestController
@RequestMapping("/app")
public class MainController{
    
	private final static Logger logger = LoggerFactory.getLogger(MainController.class);
	
	@Resource
	private UserService userService;
	
	@Resource
	private SequenceService sequenceService;
	
	@RequestMapping(value="/public/login", method=RequestMethod.POST)
	public BusiResult<Object> login(HttpServletRequest request){
		logger.info("登录开始...");
		BusiResult<Object> ret = new BusiResult<Object>();
		Map<String, String> params = RequestUtil.getParamMap(request.getParameterMap());
		logger.info("参数:{}", params);
		
		// 参数校验
		ret = ReqParamCheck.verify(ret, params, InterfaceType.LOGIN);
		if (!ret.isOk()) {
			logger.error("参数校验失败:{}", ret);
			return ret;
		}
		
		String userAccount = params.get("userAccount"); // 用户名
		String userPwd = params.get("userPwd"); // 用户密码
		
		// 查询用户
		UserExample uExample = new UserExample();
		uExample.createCriteria().andUserNameEqualTo(userAccount).andStatusEqualTo(1);
		uExample.or(uExample.createCriteria().andUserMailEqualTo(userAccount).andStatusEqualTo(1));
		uExample.or(uExample.createCriteria().andUserTelEqualTo(userAccount).andStatusEqualTo(1));
		List<User> dbUsers = userService.selectByExample(uExample);
		if (dbUsers == null || dbUsers.isEmpty()) {
			logger.error("用户不存在");
			return ret.setCoder(BusiCode.ERROR_9004);
		}
		User dbUser = dbUsers.get(0);
		
		// 验证密码
		if (!dbUser.getUserPassword().equals(MD5Util.getMD5String(userPwd))) {
			logger.error("用户名或密码错误");
			return ret.setCoder(BusiCode.ERROR_9003);
		}
		
		// 判断是否多次登录，强制下线
		if (dbUser.getSessionId() != null) {
			
		}
		
		ret.setCoder(BusiCode.ERROR_0000); // 登录成功
		
		// 生成 Session user
		User sessionUser = new User();
		BeanUtil.copyProperties(sessionUser, dbUser);
		sessionUser.setHeadphoto(null);
		sessionUser.setUserPassword(null);
		SessionCacheUtil.setSessionMap(request, "sUser", sessionUser);
		
		// 更新 user 添加 sessionid
		User upUser = new User();
		upUser.setUserId(dbUser.getUserId());
		upUser.setSessionId(SessionCacheUtil.getSessionId(request));
		userService.updateByPrimaryKeySelective(upUser);
		
		// 组织返回结果
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("userId", dbUser.getUserId());
		//result.put("nickName", dbUser.getNickName());
		// result.put("headPhoto",dbUser.getHeadphoto() == null ? null : Base64Util.encode(dbUser.getHeadphoto()));
		result.put("appSid", SessionCacheUtil.getSessionId(request));
		ret.setResult(result);
		
		logger.info("登录成功，返回:{}", ret);
		return ret;
	}
	
	@RequestMapping(value="/public/logout", method=RequestMethod.POST)
	public BusiResult<Object> logout(HttpServletRequest request){
		logger.info("用户登出");
		BusiResult<Object> ret = new BusiResult<Object>();
		Map<String, String> params = RequestUtil.getParamMap(request.getParameterMap());
		logger.info("参数:{}", params);
		
		// 参数校验
		ret = ReqParamCheck.verify(ret, params, InterfaceType.LOGOUT);
		if (!ret.isOk()) {
			logger.info("参数校验失败:{}", ret);
			return ret;
		}
		
		String userId = params.get("userId"); // 用户名
		User sUser = (User)SessionCacheUtil.getSessionMap(request).get("sUser");
		if (sUser == null) {
			logger.info("非法操作");
			return ret.setCoder(BusiCode.ERROR_9998);
		}
		if (!userId.equals(sUser.getUserId())) {
			logger.info("非法操作");
			return ret.setCoder(BusiCode.ERROR_9998);
		}
		
		// 更新 user 添加 sessionid
		User upUser = new User();
		upUser.setUserId(sUser.getUserId());
		upUser.setSessionId(null);
		userService.updateByPrimaryKeySelective(upUser);
		
		// 清除session
		SessionCacheUtil.evictSession(request);
		
		// 组织返回结果
		ret.setCoder(BusiCode.ERROR_0000);
		logger.info("登出成功");
		return ret;
	}
	
	@RequestMapping(value="/public/authcode", method=RequestMethod.POST)
	public BusiResult<Object> authcode(HttpServletRequest request){
		BusiResult<Object> ret = new BusiResult<Object>();
		logger.info("appSid-{}-验证码发送开始", SessionCacheUtil.getSessionId(request));
		Map<String, String> params = RequestUtil.getParamMap(request.getParameterMap());
		logger.info("参数:{}", params);

		// 参数校验
		ret = ReqParamCheck.verify(ret, params, InterfaceType.AUTHCODE);
		if (!ret.isOk()) {
			logger.info("参数校验失败:{}", ret);
			return ret;
		}
		
		String phoneNum = params.get("phoneNum");
		String code = StringUtil.genRandomNumber(6);
		Map<String, String> param = new HashMap<String, String>();
		param.put("code", code);
		param.put("time", "30");
		param.put("func", "签证APP身份认证");
		String extend = "20160101";
		String signName = "签证APP";
		String templateCode = "SMS_25955166";
		if (!ALISMSUtil.sendSMS(phoneNum, param, extend, signName, templateCode)) {
			ret.setCoder(BusiCode.ERROR_9010);
			return ret;
		}
		CacheUtil.setCache(CacheType.AUTH_CODE_CACHE.getCode(), SessionCacheUtil.getSessionId(request), code);
		ret.setCoder(BusiCode.ERROR_0000);
		return ret;
	}
	
	@RequestMapping(value = "/public/register")
	public BusiResult<Object> register(HttpServletRequest request){
		logger.info("注册开始...");
		BusiResult<Object> ret = new BusiResult<Object>();
		Map<String, String> params = RequestUtil.getParamMap(request.getParameterMap());
		logger.info("参数:{}", params);
		
		// 参数校验
		ret = ReqParamCheck.verify(ret, params, InterfaceType.REGISTER);
		if (!ret.isOk()) {
			logger.info("参数校验失败:{}", ret);
			return ret;
		}

		String authCode = params.get("authCode"); // 短信验证码
		String cacheCode = (String)CacheUtil.getCache(CacheType.AUTH_CODE_CACHE.getCode(), SessionCacheUtil.getSessionId(request));
		if (!authCode.equals(cacheCode)) {
			logger.error("authcode error - cache:{} - user:{}", cacheCode, authCode);
			ret.setCoder(BusiCode.ERROR_9011);
			return ret;
		}
		CacheUtil.clearCache(CacheType.AUTH_CODE_CACHE.getCode(),  SessionCacheUtil.getSessionId(request)); 
		String userAccount = params.get("userAccount"); // 用户名
		String userPwd = params.get("userPwd"); // 用户密码
		String nickName = params.get("nickName"); // 昵称
		String headPhoto = params.get("headPhoto"); // 头像
		User newUser = new User();
		
		// 判断用户名是否被注册
		UserExample uEx = new UserExample();
		UserExample.Criteria uExCr = uEx.createCriteria();
		if (userAccount.matches("^[1][0-9]{10}$")) {
			uExCr.andUserTelEqualTo(userAccount);
			newUser.setUserTel(userAccount);
		} else {
			uExCr.andUserMailEqualTo(userAccount);
			newUser.setUserMail(userAccount);
		}
		List<User> users = userService.selectByExample(uEx);
		if (users != null && !users.isEmpty()) {
			logger.info("用户名已被注册：{}", userAccount);
			return ret.setCoder(BusiCode.ERROR_9009);
		}
		
		// 注册
		newUser.setUserId(sequenceService.getCommonSequence());
		newUser.setUserPassword(MD5Util.getMD5String(userPwd));
		newUser.setNickName(nickName);
		if (StringUtil.isNotEmpty(headPhoto)) {
			try {
				newUser.setHeadphoto(headPhoto.getBytes("UTF-8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		int c = userService.insertSelective(newUser);
		if (c != 1) {
			logger.info("插入新用户数据失败：", userAccount);
			return ret.setCoder(BusiCode.ERROR_9999);
		}
		ret.setCoder(BusiCode.ERROR_0000);
		Map<String, String> result = new HashMap<String, String>();
		result.put("appSid", SessionCacheUtil.getSessionId(request));
		result.put("userId", newUser.getUserId());
		ret.setAttach(result);
		logger.info("注册成功，返回:{}", ret);
		return ret;
	}
	
	@RequestMapping(value = "/public/findpassword")
	public BusiResult<Object> findpassword(HttpServletRequest request){
		logger.info("找回密码开始...");
		BusiResult<Object> ret = new BusiResult<Object>();
		Map<String, String> params = RequestUtil.getParamMap(request.getParameterMap());
		logger.info("参数:{}", params);
		
		// 参数校验
		ret = ReqParamCheck.verify(ret, params, InterfaceType.FINDPWD);
		if (!ret.isOk()) {
			logger.info("参数校验失败:{}", ret);
			return ret;
		}
		
		String authCode = params.get("authCode"); // 短信验证码
		String cacheCode = (String)CacheUtil.getCache(CacheType.AUTH_CODE_CACHE.getCode(), SessionCacheUtil.getSessionId(request));
		if (!authCode.equals(cacheCode)) {
			logger.error("authcode error - cache:{} - user:{}", cacheCode, authCode);
			ret.setCoder(BusiCode.ERROR_9011);
			return ret;
		}
		String userAccount = params.get("userAccount"); // 用户名
		String newPwd = params.get("newPwd"); // 用户密码
		
		// 修改密码
		UserExample uEx = new UserExample();
		UserExample.Criteria uExCr = uEx.createCriteria();
		User upUser = new User();
		if (userAccount.matches("^[1][0-9]{10}$")) {
			uExCr.andUserTelEqualTo(userAccount);
		} else {
			uExCr.andUserMailEqualTo(userAccount);
		}
		upUser.setUserPassword(MD5Util.getMD5String(newPwd));
		int c = userService.updateByExampleSelective(upUser, uEx);
		if (c != 1) {
			logger.info("修改用户密码失败：", userAccount);
			return ret.setCoder(BusiCode.ERROR_9999);
		}
		ret.setCoder(BusiCode.ERROR_0000);
		logger.info("注册成功，返回:{}", ret);
		return ret;
	}
	
	@RequestMapping(value = "/public/changepassword")
	public BusiResult<Object> changepassword(HttpServletRequest request){
		logger.info("找回密码开始...");
		BusiResult<Object> ret = new BusiResult<Object>();
		Map<String, String> params = RequestUtil.getParamMap(request.getParameterMap());
		logger.info("参数:{}", params);
		
		// 参数校验
		ret = ReqParamCheck.verify(ret, params, InterfaceType.CHANGEPWD);
		if (!ret.isOk()) {
			logger.info("参数校验失败:{}", ret);
			return ret;
		}
		
		String userAccount = params.get("userAccount"); // 用户名
		String newPwd = params.get("newPwd"); // 新密码
		String oldPwd = params.get("oldPwd"); // 旧密码
		// 判断用户名是否被注册
		UserExample uEx = new UserExample();
		UserExample.Criteria uExCr = uEx.createCriteria();
		if (userAccount.matches("^[1][0-9]{10}$")) {
			uExCr.andUserTelEqualTo(userAccount);
		} else {
			uExCr.andUserMailEqualTo(userAccount);
		}
		List<User> users = userService.selectByExample(uEx);
		if (users != null && !users.isEmpty()) {
			logger.error("用户名不存在：{}", userAccount);
			return ret.setCoder(BusiCode.ERROR_9004);
		}
		User dbUser = users.get(0);
		if (!MD5Util.getMD5String(oldPwd).equals(dbUser.getUserPassword())) {
			logger.error("原密码错误：{}", userAccount);
			return ret.setCoder(BusiCode.ERROR_9003);
		}
		User upUser = new User();
		upUser.setUserPassword(MD5Util.getMD5String(newPwd));
		int c = userService.updateByExampleSelective(upUser, uEx);
		if (c != 1) {
			logger.info("修改用户密码失败：", userAccount);
			return ret.setCoder(BusiCode.ERROR_9999);
		}
		ret.setCoder(BusiCode.ERROR_0000);
		logger.info("注册成功，返回:{}", ret);
		return ret;
	}
	
	@RequestMapping("/init")
	public BusiResult<Object> init(HttpServletRequest request){
		BusiResult<Object> ret = new BusiResult<Object>();
		
		logger.info("初始化开始...");
		String ip = RequestUtil.getIp(request);
		String appSid = request.getParameter(SessionCacheUtil.SESSION_FLAG);
		String appVersion = request.getParameter("appVersion");
		logger.info("IP:{}", ip);
		logger.info("appSid:{}", appSid);
		logger.info("appVersion:{}", appVersion);
		
		// 判断版本是否可用
		if (!"1.0.0.0".equals(appVersion)) {
			logger.info("版本不可用：{}", appVersion);
			return ret.setCoder(BusiCode.ERROR_9008);
		}
		
		// 判断是否重新生成appSid
		String newSid = appSid;
		Boolean isNew = false;
		Map<String, Object> sessionMap = SessionCacheUtil.getSessionMap(request);
		if (sessionMap == null || (sessionMap.get("isKickOut") != null && (Boolean)sessionMap.get("isKickOut"))) {
			isNew = true;
		}
		
		// 生成新的sessionid 并添加到session会话管理缓存中
		if (isNew) {
			newSid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
			SessionCacheUtil.setCache(newSid, new HashMap<String, Object>());
		}
		
		// 返回
		ret.setCoder(BusiCode.ERROR_0000);
		Map<String, Object> result = new HashMap<String, Object>();
		result.put(SessionCacheUtil.SESSION_FLAG, newSid);
		ret.setResult(result);
		logger.info("初始化成功，返回:{}", ret);
		return ret;
	}
	
	/**
	 * 错误返回
	 * @param errorCode
	 * @return
	 */
	@RequestMapping("/error")
	public BusiResult<Object> init(String errorCode){
		BusiResult<Object> ret = new BusiResult<Object>();
		ret.setCoder(BusiCode.getCode(errorCode));
		return ret;
	}
	
	

}
